home *** CD-ROM | disk | FTP | other *** search
- /* SCSIInquiry.c */
- /*
- * SCSIInquiry.c
- * Copyright © 1994 Apple Computer Inc. All rights reserved.
- * This is a minimal sample to illustrate the Old SCSI Manager.
- */
- #include "SCSIInquiry.h"
-
- #ifndef THINK_C /* MPW includes */
- #include <Errors.h>
- #include <Script.h>
- #include <Types.h>
- #include <Files.h>
- #include <Resources.h>
- #include <QuickDraw.h>
- #include <Fonts.h>
- #include <Events.h>
- #include <Windows.h>
- #include <ToolUtils.h>
- #include <Memory.h>
- #include <Menus.h>
- #include <Lists.h>
- #include <Printing.h>
- #include <Dialogs.h>
- #include <StandardFile.h>
- #endif
-
- #include <SCSI.h>
-
- unsigned short gTargetDevice = 0; /* Using device at ID = 0 */
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * SCSI Definitions
- */
- #define kScsiStatusGood 0x00 /* Normal completion */
- #define kScsiCmdInquiry 0x12 /* Device inquiry command */
-
- struct SCSI_6_Byte_Command { /* Six-byte command */
- unsigned char opcode; /* 0 */
- unsigned char lbn3; /* 1 lbn in low 5 */
- unsigned char lbn2; /* 2 */
- unsigned char lbn1; /* 3 */
- unsigned char len; /* 4 */
- unsigned char ctrl; /* 5 */
- };
- typedef struct SCSI_6_Byte_Command SCSI_6_Byte_Command;
-
- struct SCSI_Inquiry_Data { /* Inquiry returns this */
- unsigned char devType; /* 0 Device type, */
- unsigned char devTypeMod; /* 1 Device type modifier */
- unsigned char version; /* 2 ISO/ECMA/ANSI version */
- unsigned char format; /* 3 Response data format */
- unsigned char length; /* 4 Additional Length */
- unsigned char reserved5; /* 5 Reserved */
- unsigned char reserved6; /* 6 Reserved */
- unsigned char flags; /* 7 Capability flags */
- unsigned char vendor[8]; /* 8-15 Vendor-specific */
- unsigned char product[16]; /* 16-31 Product id */
- unsigned char revision[4]; /* 32-35 Product revision */
- unsigned char vendorSpecific[20]; /* 36-55 Vendor stuff */
- unsigned char moreReserved[40]; /* 56-95 Reserved */
- };
- typedef struct SCSI_Inquiry_Data SCSI_Inquiry_Data;
-
- SCSI_Inquiry_Data gInquiryData; /* Inquiry data goes here */
- unsigned long gInquirySize; /* Number of bytes read */
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * gSCSICommand is the command that we send to the device.
- */
- SCSI_6_Byte_Command gSCSICommand = {
- kScsiCmdInquiry, /* Command */
- 0, /* LBN 3 -- unused */
- 0, /* LBN 2 -- unused */
- 0, /* LBN 1 -- unused */
- sizeof (SCSI_Inquiry_Data), /* Returned buffer length */
- 0 /* Flags -- must be zero */
- };
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * gRequestTIB defines the buffer that SCSIRead reads into. Because
- * the Inquiry command can return a variable-length record, we use a
- * TIB with single-byte transfers and an internal counter so we can
- * recover the actual transfer length. The four tib values are used
- * as follows:
- * scInc... Move one byte from the device to the buffer address
- * and increment the buffer address pointer.
- * scAdd... Add one to gInquirySize -- this gives the actual
- * number of bytes transfered.
- * scLoop Continue processing TIB instructions at the start
- * until the maximum number of loops have been done.
- * scStop End of the TIB.
- * Note that this is an extremely inefficient TIB and should only be
- * used for polled "administrative" requests that return a variable-
- * length buffer.
- */
- SCSIInstr gRequestTIB[] = {
- { scInc, 0, 1 },
- { scAdd, 0, 1 },
- { scLoop, (-2 * sizeof (SCSIInstr)), sizeof (SCSI_Inquiry_Data) },
- { scStop, 0, 0 }
- };
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Local functions and administrative variables.
- */
- #ifdef __powerc
- QDGlobals qd;
- #endif
-
- void DisplayError(
- OSErr errorStatus
- );
- OSErr DoSCSICommand(
- unsigned short targetID,
- const Ptr scsiCommand,
- SCSIInstr *requestTIB
- );
- void DisplaySCSIInquiry(
- long actualTransferCount
- );
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Local functions and administrative variables.
- */
- void
- main(void)
- {
- short i;
- OSErr status;
- OSErr completionStatus;
- EventRecord eventRecord;
- long actualTransferCount;
- unsigned long watchdog;
- short stsByte;
- short msgByte;
-
- MaxApplZone();
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0);
- for (i = 0; i < 3; i++)
- EventAvail(everyEvent, &eventRecord);
- gRequestTIB[0].scParam1 = (unsigned long) &gInquiryData;
- gRequestTIB[1].scParam1 = (unsigned long) &gInquirySize;
- /*
- * This is a simplified form of the "Get Bus" protocol.
- */
- watchdog = TickCount() + 300;
- while ((status = SCSIGet()) != noErr && TickCount() < watchdog)
- ;
- if (status == noErr)
- status = SCSISelect(gTargetDevice);
- if (status == noErr) {
- status = SCSICmd((Ptr) &gSCSICommand, sizeof gSCSICommand);
- if (status == noErr)
- status = SCSIRead((Ptr) gRequestTIB);
- completionStatus = SCSIComplete(&stsByte, &msgByte, 5 * 60);
- if (status == noErr && completionStatus != noErr)
- status = completionStatus;
- if (status == scPhaseErr && stsByte == kScsiStatusGood)
- status = noErr;
- if (status == noErr && stsByte != kScsiStatusGood)
- status = ioErr;
- }
- /*
- * Since the Device Inquiry command can return a variable-length
- * record, we need to obtain the actual number of bytes that
- * were read. There are two algorithms we can use here, that
- * should result in the same data:
- * Since tib[0].scOpcode was scInc, tib[0].scParam1 will point to
- * the next byte to store. We can subtract the original buffer
- * pointer from that value to get the actual count.
- * Since tib[1].scOpcode was scAdd, gInquirySize will have the
- * actual count.
- * One or another of these two techniques can be used for this
- * type of data.
- */
- actualTransferCount =
- gRequestTIB[0].scParam1 - (unsigned long) &gInquiryData;
- if (actualTransferCount != gInquirySize)
- DisplayError(paramErr);
- if (status != noErr)
- DisplayError(status);
- DisplaySCSIInquiry(actualTransferCount);
- ExitToShell();
- }
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Display the inquiry result.
- */
- static void
- StoreString(
- const unsigned char *textPtr,
- Size textLength,
- StringPtr result
- )
- {
- register short i;
-
- for (i = textLength; i > 0; --i) {
- if (textPtr[i - 1] != ' ' && textPtr[i - 1] != 0)
- break;
- }
- BlockMove(textPtr, &result[1], i);
- result[0] = i;
- }
-
- void
- DisplaySCSIInquiry(
- long actualTransferCount
- )
- {
- Str255 inquirySize;
- Str255 vendorName;
- Str255 productName;
- Str255 revisionLevel;
-
- NumToString(actualTransferCount, inquirySize);
- StoreString(
- gInquiryData.vendor,
- sizeof gInquiryData.vendor,
- vendorName
- );
- StoreString(
- gInquiryData.product,
- sizeof gInquiryData.product,
- productName
- );
- StoreString(
- gInquiryData.revision,
- sizeof gInquiryData.revision,
- revisionLevel
- );
- ParamText(inquirySize, vendorName, productName, revisionLevel);
- NoteAlert(ALRT_Info, NULL);
- }
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Display an error alert.
- */
- void
- DisplayError(
- OSErr errorStatus
- )
- {
- Str255 work;
-
- NumToString(errorStatus, work);
- ParamText(work, "\p", "\p", "\p");
- InitCursor();
- StopAlert(ALRT_Error, NULL);
- }
-
-